#pragma once

#include <iostream>
#include <vector>

#define SEP "X"
#define SEP_LEN strlen(SEP)

#define SPACE " "
#define SPACE_LEN strlen(SPACE)

// 处理粘包问题，将完整的报文分开
                                                /*vs就是处理完整个包后的所有的完整小包，输出*/
void SplitMessage(std::string &message, std::vector<std::string> &vs)
{        /*message就是黏在一块的包，也就是接收缓冲区中的数据，输出*/      
    while(1)
    {
        // 先找到其中的SEP
        size_t pos = message.find(SEP);
        if(pos == std::string::npos)
        { // 没有SEP，也就是没有完整报文了
            break;
        }
        // 取出一个完整的包
        std::string tmp = message.substr(0, pos);
        // 删掉接收缓冲区中刚刚的包
        message.erase(0, pos + SEP_LEN);
        // 将完整的包添加到vs中
        vs.push_back(tmp);
    }
}

void Encode(std::string &s)
{
    s += SEP;
}

// 请求中的字段
class Request
{
public:
    // 这里是原来客户端用的，但是这里没有写客户端就不用这个了。
    std::string Serialize()
    {
        std::string str;
        str = std::to_string(x_);
        str += SPACE;
        str += op_; // TODO
        str += SPACE;
        str += std::to_string(y_);
        return str;
    }

    // 这个是给服务端用的，用来将完整报文中的字段分出来
    bool Deserialized(const std::string &str) // 1 + 1
    {
        std::size_t left = str.find(SPACE);
        if (left == std::string::npos)
            return false;
        std::size_t right = str.rfind(SPACE);
        if (right == std::string::npos)
            return false;
        x_ = atoi(str.substr(0, left).c_str());
        y_ = atoi(str.substr(right + SPACE_LEN).c_str());
        if (left + SPACE_LEN > str.size())
            return false;
        else
            op_ = str[left + SPACE_LEN];
        return true;
    }

public:
    Request()
    {
    }
    Request(int x, int y, char op) : x_(x), y_(y), op_(op)
    {
    }
    ~Request() {}

public:
    int x_;   // 是什么？
    int y_;   // 是什么？
    char op_; // '+' '-' '*' '/' '%'
};

// 响应
class Response
{
public:
    // 这给是给服务端用的，用来将响应中的结果序列化
    std::string Serialize()
    {
        std::string s;
        s = std::to_string(code_);
        s += SPACE;
        s += std::to_string(result_);

        return s;
    }

    // 这是给客户端用的，但是也是没写，所以派不上用场
    bool Deserialized(const std::string &s)
    {
        std::size_t pos = s.find(SPACE);
        if (pos == std::string::npos)
            return false;
        code_ = atoi(s.substr(0, pos).c_str());
        result_ = atoi(s.substr(pos + SPACE_LEN).c_str());
        return true;
    }
public:
    Response()
    {
    }
    Response(int result, int code) : result_(result), code_(code)
    {
    }
    ~Response() {}

public:
    int result_; // 计算结果
    int code_;   // 计算结果的状态码
};